#pragma once
#include <array>

struct Vec2 { double x; double y; };

inline Vec2 operator+(const Vec2& a, const Vec2& b) { return {a.x+b.x, a.y+b.y}; }
inline Vec2 operator-(const Vec2& a, const Vec2& b) { return {a.x-b.x, a.y-b.y}; }
inline Vec2 operator*(const Vec2& a, double s) { return {a.x*s, a.y*s}; }
inline Vec2 operator/(const Vec2& a, double s) { return {a.x/s, a.y/s}; }

struct Body { double m; Vec2 p; Vec2 v; };

struct State { std::array<Body,3> b; };

struct Deriv { std::array<Vec2,3> dp; std::array<Vec2,3> dv; };

struct PhysParams { double G; double eps; double dt; };

void reset_initial(State& s);
void reset_figure_eight(State& s);
void reset_solar(State& s);
void reset_figure_eight_loose(State& s);
double total_energy(const State& s, const PhysParams& p);
Deriv eval(const State& s, const PhysParams& p);
void integrate_rk4(State& s, const PhysParams& p);